"""
装饰器 - 用一个函数去装饰别的函数或者类，为它们提供额外的能力，这个函数就称为装饰器函数。
这里所指的能力，通常是跟被装饰的函数正常的业务没有必然联系的功能，更专业的说法叫横切关注功能。
横切关注功能最好不要写在原函数上，因为会影响代码的质量，而且会产生重复代码。
Python中的装饰器实现了设计模式中的代理模式，这种设计模式可以用来处理横切关注功能。

设计模式：在特定场景下可以复用的设计理念。---> 1995 ---> 23场景 ---> GoF设计模式

好的代码：高内聚，低耦合
高内聚：一个类、一个函数，只做该做的事情，尽量只做好一件事情
低耦合：类之间，函数之间，尽量减少相互的依赖，让依赖发生在更抽象的层面上
"""
import asyncio

import aiohttp
import bs4

address = 'https://static4.scrape.center/page/'


def retry(*, retry_times=3, wait_time=5, errors=(Exception, )):

    def decorate(func):

        async def wrapper(*args, **kwargs):
            for _ in range(retry_times):
                try:
                    return await func(*args, **kwargs)
                except errors as err:
                    print(err)
                    await asyncio.sleep(wait_time)

        return wrapper

    return decorate


@retry(retry_times=5, wait_time=15)
async def get_movies(page_num):
    url = address + str(page_num)
    timeout = aiohttp.ClientTimeout(total=600)
    async with aiohttp.ClientSession(timeout=timeout) as session:
        async with session.get(url, ssl=False) as resp:
            html_code = await resp.text()
            soup = bs4.BeautifulSoup(html_code, 'html.parser')
            tags = soup.select('.m-b-sm')
            for tag in tags:
                print(tag.text)


def main():
    task_list = [get_movies(x) for x in range(1, 11)]
    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.wait(task_list))


if __name__ == '__main__':
    main()
